# -*- coding: utf-8 -*-
from __future__ import division
from __future__ import print_function

from ..ops import Max, Min, Mean
from ..base import OpsFeature

from .close import Close
from .high import High
from .low import Low

class RSV(OpsFeature):
    """Technical Indicator - RSV

    - RSV = (CLOSE - MIN(LOW, N)) / (MAX(HIGH, N) - MIN(LOW, N)) * 100
    """
    def __init__(self, N=9):
        self.N = N

    def __str__(self):
        name = type(self).__name__.lower()
        if self.N != 9:
            name += '_'+str(self.N)
        return name

    def _load_internal(self, instrument, start_time, end_time, freq):
        rsv = (Close() - Min(Low(), self.N)) / (Max(High(), self.N) - Min(Low(), self.N)) * 100
        return rsv.load(instrument, start_time, end_time, freq)


class KDJK(OpsFeature):
    """Technical Indicator - KDJ (K)

    - KDJK = MA(RSV, M)
    """
    def __init__(self, N1=9, N2=3):
        self.N1 = N1
        self.N2 = N2

    def __str__(self):
        name = type(self).__name__.lower()
        if self.N1 != 9 or self.N2 != 3:
            name += '_{}_{}'.format(self.N1, self.N2)
        return name
    
    def _load_internal(self, instrument, start_time, end_time, freq):
        k = Mean(RSV(self.N1), self.N2)
        return k.load(instrument, start_time, end_time, freq)


class KDJD(OpsFeature):
    """Technical Indicator - KDJ (D)

    - KDJD = MA(KDJK, M)
    """
    def __init__(self, N1=9, N2=3, N3=3):
        self.N1 = N1
        self.N2 = N2
        self.N3 = N3

    def __str__(self):
        name = type(self).__name__.lower()
        if self.N1 != 9 or self.N2 != 3 or self.N3 != 3:
            name += '_{}_{}_{}'.format(self.N1, self.N2, self.N3)
        return name
    
    def _load_internal(self, instrument, start_time, end_time, freq):
        d = Mean(KDJK(self.N1, self.N2), self.N3)
        return d.load(instrument, start_time, end_time, freq)


class KDJJ(OpsFeature):
    """Technical Indicator - KDJ (J)

    - KDJJ = 3*KDJK - 2*KDJD
    """
    def __init__(self, N1=9, N2=3, N3=3):
        self.N1 = N1
        self.N2 = N2
        self.N3 = N3

    def __str__(self):
        name = type(self).__name__.lower()
        if self.N1 != 9 or self.N2 != 3 or self.N3 != 3:
            name += '_{}_{}_{}'.format(self.N1, self.N2, self.N3)
        return name
    
    def _load_internal(self, instrument, start_time, end_time, freq):
        k = KDJK(self.N1, self.N2)
        d = KDJD(self.N1, self.N2, self.N3)
        j = 3*k - 2*d
        return j.load(instrument, start_time, end_time, freq)
